package com.dc.di.sf.utils;

import java.io.CharArrayWriter;
import java.io.InputStream;
import java.io.Writer;
import java.util.Iterator;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.impl.dom.ElementImpl;
import org.apache.axis2.util.XMLUtils;
import org.pentaho.di.core.util.StringUtil;
import org.w3c.dom.Element;

import com.dc.di.sf.dt.Constants;

public class OMUtils {

	private static OMFactory fac = OMAbstractFactory.getOMFactory();

	public static QName createQName(String name) {
		return new QName(Constants.NAMESPACE_CNEGD_URL, name);
	}

	public static OMElement createOMElement(String name) {
		return fac.createOMElement(name, Constants.NAMESPACE_CNEGD);
	}

	public static OMElement createOMElementWithText(String name, String text) {
		OMElement el = fac.createOMElement(name, Constants.NAMESPACE_CNEGD);
		el.setText(text);
		return el;
	}

	public static String getTextOfChild(OMElement el, String name) {
		OMElement child = el.getFirstChildWithName(new QName(Constants.NAMESPACE_CNEGD_URL, name));
		if (child != null)
			return child.getText();
		return null;
	}

	public static Iterator getChildren(OMElement el, String name) {
		return el.getChildrenWithName(new QName(Constants.NAMESPACE_CNEGD_URL, name));
	}

	public static void validate(OMElement omElement, InputStream schemaSource) throws Exception {

		Element sourceElement;

		// if the OMElement is created using DOM implementation use it
		if (omElement instanceof ElementImpl) {
			sourceElement = (Element) omElement;
		} else { // else convert from llom to dom
			sourceElement = XMLUtils.toDOM(omElement);
		}

		// Create a SchemaFactory capable of understanding WXS schemas.
		// Load a WXS schema, represented by a Schema instance.
		SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		Source source = new StreamSource(schemaSource);

		// Create a Validator object, which can be used to validate an instance
		// document.
		Schema schema = factory.newSchema(source);
		Validator validator = schema.newValidator();

		// Validate the DOM tree.
		validator.validate(new DOMSource(sourceElement));
	}

	public static String generateOMElementBeginString(String name) {
		return generateOMElementBeginString(name, Constants.NAMESPACE_CNEGD_PREFIX, null);
	}

	public static String generateOMElementBeginString(String name, String prefix, String uri) {
		StringBuilder sb = new StringBuilder();
		sb.append("<");
		if (!StringUtil.isEmpty(prefix))
			sb.append(prefix).append(":");
		sb.append(name);
		if (!StringUtil.isEmpty(uri)) {
			sb.append(" ").append("xmlns");
			if (!StringUtil.isEmpty(prefix))
				sb.append(":").append(prefix);
			sb.append("=").append("\"").append(uri).append("\"");
		}
		sb.append(">");
		return sb.toString();
	}

	public static String generateOMElementEndString(String name) {
		return generateOMElementEndString(name, Constants.NAMESPACE_CNEGD_PREFIX);
	}

	public static String generateOMElementEndString(String name, String prefix) {
		StringBuilder sb = new StringBuilder();
		sb.append("</");
		if (!StringUtil.isEmpty(prefix))
			sb.append(prefix).append(":");
		sb.append(name).append(">");
		return sb.toString();
	}

	public static String generateOMElementString(String name, String text) {
		return generateOMElementString(name, Constants.NAMESPACE_CNEGD_PREFIX, null, text);
	}

	public static String generateOMElementString(String name, String prefix, String uri, String text) {
		StringBuilder sb = new StringBuilder();
		sb.append(generateOMElementBeginString(name, prefix, uri));
		if (!StringUtil.isEmpty(text)) {
			Writer writer = new CharArrayWriter();
			try {
				WriterUtility util = new WriterUtility(writer);
				util.writeXMLContent(text);
			} catch (Exception e) {
				throw new RuntimeException("Can not serialize text " + text, e);
			}
			sb.append(writer.toString());
//			sb.append(text);
		}
		sb.append(generateOMElementEndString(name, prefix));
		return sb.toString();
	}

}
